﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Configuration;

namespace EventNotificationService
{
    public partial class EventNotificationService : ServiceBase
    {
       private ServiceModuleSection _services;
//        private SettingsSection _settings;
        private Database _db;

        private System.Timers.Timer timerService;

        public EventNotificationService()
        {
            timerService = new System.Timers.Timer();
            timerService.Elapsed += new System.Timers.ElapsedEventHandler(timerService_Tick);
            InitializeComponent();
            LoadConfiguration();
            
            _db = DatabaseFactory.CreateDatabase("EventDatabase");

            if (_db == null)
            {
                Logger.Write(String.Format(Properties.Resources.UnableToOpenDatabase, "EventDatabase"), "Database", 0, 2, TraceEventType.Error);
                return;
            }

            Logger.Write("Class Initialized", "General", 0, 7001, TraceEventType.Verbose);
        }

        new protected void Dispose()
        {
            timerService.Dispose();
            base.Dispose();
        }

        
        private void LoadConfiguration()
        {
  /*          object section1 = ConfigurationManager.GetSection(SettingsSection.SectionName);
            _settings = section1 as SettingsSection;

            if (_settings == null)
            {
                throw new ConfigurationErrorsException(String.Format(
                    CultureInfo.CurrentCulture,
                    Properties.Resources.MissingConfigurationSection,
                    SettingsSection.SectionName));
            }
  */
            object section2 = ConfigurationManager.GetSection(ServiceModuleSection.SectionName);
            _services = section2 as ServiceModuleSection;

            if (_services == null)
            {
                throw new ConfigurationErrorsException(String.Format( CultureInfo.CurrentCulture,
                    Properties.Resources.MissingConfigurationSection,
                    ServiceModuleSection.SectionName));
            }
        }

        protected override void OnStart(string[] args)
        {
            LoadConfiguration();
            Logger.Write("Service Started", "General", 0, 7002, TraceEventType.Verbose);
            timerService.Interval = Properties.Settings.Default.PollingInterval;
            timerService.Start();
            // TODO: Add code here to start your service.
        }

        protected override void OnStop()
        {
            timerService.Stop();
            // TODO: Add code here to perform any tear-down necessary to stop your service.
        }

        void timerService_Tick(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Properties.Settings.Default.Trace)
            {
                Logger.Write("Start Processing Events", "General", 0, 7003, TraceEventType.Verbose);
            }

            timerService.Stop();
            try
            {
                System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(Properties.Settings.Default.SMTPServer);
                
                if( Properties.Settings.Default.SMTPAuthentication )
                    client.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

                foreach (ServiceElement service in _services.Services)
                {
                    if (service.BodyTemplate == null || service.BodyTemplate.Trim() == String.Empty)
                    {
                        Logger.Write(String.Format(Properties.Resources.BlankBodyTemplate, service.ServiceName), "General", 0, 2002, TraceEventType.Error);
                        continue;
                    }

                    string bodyTemplate = ReadBodyTemplate(service.BodyTemplate);
                    if (bodyTemplate == null)
                    {
                        Logger.Write(String.Format(Properties.Resources.BlankBodyTemplate, service.ServiceName), "General", 0, 2002, TraceEventType.Error);
                        continue;
                    }

                    DataSet dsOrders = RetrieveEvents(service.EventTableName, service.ServiceName);
                    if (dsOrders == null || dsOrders.Tables[0] == null || dsOrders.Tables[0].Rows.Count == 0)
                    {
                        if (Properties.Settings.Default.Trace)
                        {
                            Logger.Write(String.Format(Properties.Resources.NoNewEventFound, service.ServiceName), "General", 0, 7004, TraceEventType.Verbose);
                        }

                        continue;
                    }


                    foreach (DataRow dr in dsOrders.Tables[0].Rows)
                    {
                        string body = bodyTemplate;
                        string subjectline = service.SubjectLine;

                        body = body.Replace("[TODAY]", DateTime.Today.ToString("MM/dd/yyyy"));
                        subjectline = subjectline.Replace("[TODAY]", DateTime.Today.ToString("MM/dd/yyyy"));
                        foreach (DataColumn dc in dsOrders.Tables[0].Columns)
                        {
                            body = body.Replace("[" + dc.ColumnName.ToUpper().Trim() + "]", dr[dc].ToString());
                            subjectline = subjectline.Replace("[" + dc.ColumnName.ToUpper().Trim() + "]", dr[dc].ToString());
                        }

                        string toAddress = service.ToAddress;
                        string ccAddress = service.CCAddress;
                        if (toAddress.IndexOf("[RECIPI") >= 0)
                        {
                            if (!Convert.IsDBNull(dr["RecipientAddress"]))
                            {
                                toAddress = toAddress.Replace("[RECIPIENTADDRESS]", dr["RecipientAddress"].ToString());
                            }
                            else
                            {
                                toAddress = toAddress.Replace("[RECIPIENTADDRESS]", "");
                            }

                            if (!Convert.IsDBNull(dr["RecipientAddress2"]))
                            {
                                toAddress = toAddress.Replace("[RECIPIENTADDRESS2]", dr["RecipientAddress2"].ToString());
                            }
                            else
                            {
                                toAddress = toAddress.Replace("[RECIPIENTADDRESS2]", "");
                            }

                        }

                        if (toAddress == null)
                        {
                            Logger.Write(String.Format(Properties.Resources.NoValidEmailAddress, service.ServiceName, dr["EventID"].ToString()));
                            continue;
                        }


                        if (ccAddress != null)
                        {
                            if (!Convert.IsDBNull(dr["RecipientAddress"]))
                            {
                                ccAddress = ccAddress.Replace("[RECIPIENTADDRESS]", dr["RecipientAddress"].ToString());
                            }
                            else
                                ccAddress = ccAddress.Replace("[RECIPIENTADDRESS]", "");

                            if (!Convert.IsDBNull(dr["RecipientAddress2"]))
                                ccAddress = ccAddress.Replace("[RECIPIENTADDRESS2]", dr["RecipientAddress2"].ToString());
                            else
                                ccAddress = ccAddress.Replace("[RECIPIENTADDRESS2]", "");
                        }
                        
                        System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
                        message.From = new System.Net.Mail.MailAddress(service.FromAddress);
                        message.Subject = subjectline;
                        message.Body = body;
                        if (toAddress != null && toAddress != string.Empty)
                        {
                            string[] toArray = toAddress.Split(';');
                            if (toArray != null && toArray.Length > 0)
                            {
                                foreach (string addr in toArray)
                                {
                                    if( addr != string.Empty )
                                        message.To.Add(addr);
                                }
                            }
                        }
                        //message.IsBodyHtml = true;
                        //message.Body = body;
                        if (ccAddress != null && ccAddress != string.Empty)
                        {
                            string[] ccArray = ccAddress.Split(';');
                            if (ccArray != null && ccArray.Length > 0)
                            {
                                foreach (string addr in ccArray)
                                {
                                    if (addr != null && addr != string.Empty)
                                    {
                                        message.CC.Add(addr);
                                    }
                                }
                            }
                        }

                    
                        client.Send(message);


                        message.Dispose();

                        UpdateEventStatus(service.EventTableName, Convert.ToInt32(dr["EventID"]));

                        if (Properties.Settings.Default.Trace)
                        {
                            Logger.Write("Event Notification Sent", "General", 0, 2002, TraceEventType.Verbose);
                        }
                    
                    }

                    

                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex.Message, "General", 0, 2001, TraceEventType.Error, "Error Sending Notifications");
            }
            
            timerService.Start();
        }


        private DataSet RetrieveEvents(string eventTable, string serviceName)
        {
            return _db.ExecuteDataSet(CommandType.Text, " select * from " + eventTable + " where EventService = '" + serviceName + "' and EventStatus = 0");
        }

        private void UpdateEventStatus(string eventTable, int eventID)
        {
            _db.ExecuteNonQuery(CommandType.Text, "update " + eventTable + " set EventStatus = 1, DateNotified = getdate() where EventID = " + eventID.ToString().Trim());
        }

        private string ReadBodyTemplate(string filePath)
        {
            StreamReader input;

            try
            {
                if( File.Exists( filePath ))
					input = new StreamReader( filePath );
				else
				{
                    Logger.Write(String.Format(Properties.Resources.BodyTemplateNotExist, filePath));
					return null;
				}

            }
            catch (Exception ex)
            {
                Logger.Write(String.Format(Properties.Resources.UnableToOpenTemplate, filePath, ex.Message));
                return null;
            }

            string _content;

            try
            {
                _content = input.ReadToEnd();
            }
            catch (Exception ex1)
            {
                Logger.Write(String.Format(Properties.Resources.UnableToReadTemplate, filePath, ex1.Message));
                return null;
            }

            input.Close();
            input.Dispose();

            return _content;
        }

    
    }
}
